#include "serial_manager.h"
#include "../config/config.h"
#include <iostream>

// Global variables
extern BaseConfig baseConfig;

void SerialManager::show_serial_config_dialog(GtkWidget *parent, GtkBuilder *builder) {
    GtkBuilder *dialog_builder = gtk_builder_new();
    
    // Load UI file directly from the UI directory relative to the executable
    char* exec_path = g_file_read_link("/proc/self/exe", NULL);
    char* ui_path = nullptr;
    
    if (exec_path) {
        char* exec_dir = g_path_get_dirname(exec_path);
        ui_path = g_build_filename(exec_dir, "UI", "serial_config_dialog.glade", NULL);
        g_free(exec_dir);
        g_free(exec_path);
    }
    
    GError *error = nullptr;
    bool ui_loaded = false;
    if (ui_path) {
        if (gtk_builder_add_from_file(dialog_builder, ui_path, &error)) {
            ui_loaded = true;
        } else {
            std::cerr << "无法加载串口配置对话框UI文件: " << error->message << std::endl;
            g_error_free(error);
        }
        g_free(ui_path);
    }
    
    if (!ui_loaded) {
        std::cerr << "无法加载串口配置对话框UI文件" << std::endl;
        g_object_unref(dialog_builder);
        return;
    }
    
    GtkWidget *dialog = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "serial_config_dialog"));
    if (!dialog) {
        std::cerr << "无法获取串口配置对话框对象" << std::endl;
        g_object_unref(dialog_builder);
        return;
    }
    
    // Set the parent window
    gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
    
    // Save dialog builder to dialog's user data so we can access it later
    g_object_set_data(G_OBJECT(dialog), "dialog_builder", dialog_builder);
    
    // Get UI elements
    GtkWidget *port_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "port_combobox"));
    GtkWidget *baudrate_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "baudrate_combobox"));
    GtkWidget *stopbits_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "stopbits_combobox"));
    GtkWidget *databits_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "databits_combobox"));
    GtkWidget *parity_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "parity_combobox"));
    
    // Fill UI elements with current configuration
    // Set port combobox
    if (port_combobox) {
        gtk_combo_box_set_active_id(GTK_COMBO_BOX(port_combobox), baseConfig.port.c_str());
        if (gtk_combo_box_get_active_id(GTK_COMBO_BOX(port_combobox)) == nullptr) {
            // If the port is not in the list, add it
            gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(port_combobox), baseConfig.port.c_str(), baseConfig.port.c_str());
            gtk_combo_box_set_active_id(GTK_COMBO_BOX(port_combobox), baseConfig.port.c_str());
        }
    }
    
    // Set baudrate combobox
    if (baudrate_combobox) {
        gchar *baudrate_text = g_strdup_printf("%d", baseConfig.baudRate);
        gtk_combo_box_set_active_id(GTK_COMBO_BOX(baudrate_combobox), baudrate_text);
        if (gtk_combo_box_get_active_id(GTK_COMBO_BOX(baudrate_combobox)) == nullptr) {
            // If the baudrate is not in the list, add it
            gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(baudrate_combobox), baudrate_text, baudrate_text);
            gtk_combo_box_set_active_id(GTK_COMBO_BOX(baudrate_combobox), baudrate_text);
        }
        g_free(baudrate_text);
    }
    
    // Set databits combobox
    if (databits_combobox) {
        gchar *databits_text = g_strdup_printf("%d", baseConfig.dataBits);
        gtk_combo_box_set_active_id(GTK_COMBO_BOX(databits_combobox), databits_text);
        g_free(databits_text);
    }
    
    // Set stopbits combobox
    if (stopbits_combobox) {
        gchar *stopbits_text = g_strdup_printf("%d", baseConfig.stopBits);
        gtk_combo_box_set_active_id(GTK_COMBO_BOX(stopbits_combobox), stopbits_text);
        g_free(stopbits_text);
    }
    
    // Set parity combobox
    if (parity_combobox) {
        gtk_combo_box_set_active_id(GTK_COMBO_BOX(parity_combobox), baseConfig.parity.c_str());
    }
    
    // Connect signals
    gtk_builder_connect_signals(dialog_builder, builder);
    
    // Connect dialog response signal
    g_signal_connect(dialog, "response", G_CALLBACK(SerialManager::on_serial_config_response), builder);
    
    // Show dialog
    gtk_widget_show_all(dialog);
    
    // Note: We don't unref dialog_builder here because it's stored in the dialog's user data
    // and will be used later in on_serial_config_response
}

void SerialManager::on_serial_config_response(GtkDialog *dialog, gint response_id, gpointer user_data) {
    GtkBuilder *main_builder = GTK_BUILDER(user_data);
    
    if (response_id == GTK_RESPONSE_OK) {
        std::cout << "用户点击了确定按钮，开始更新配置..." << std::endl;
        
        // Get the dialog builder from the dialog's user data
        GtkBuilder *dialog_builder = GTK_BUILDER(g_object_get_data(G_OBJECT(dialog), "dialog_builder"));
        if (!dialog_builder) {
            std::cerr << "警告: 无法获取对话框构建器，将使用主构建器作为备选方案" << std::endl;
            // Fallback to main builder
            dialog_builder = main_builder;
        }
        
        // Update configuration from UI
        update_serial_config_from_ui(dialog_builder);
        
        // Save configuration to file
        std::cout << "正在保存配置到文件..." << std::endl;
        if (!saveBaseConfig("config/config.ini")) {
            std::cerr << "错误: 无法保存串口配置到文件" << std::endl;
        } else {
            std::cout << "成功保存串口配置到文件" << std::endl;
        }
        
        std::cout << "配置更新和保存完成" << std::endl;
    } else {
        std::cout << "用户取消了配置更改" << std::endl;
    }
    
    // Ensure dialog is destroyed
    if (dialog) {
        gtk_widget_destroy(GTK_WIDGET(dialog));
    }
    
    // If we used the dialog builder (not the main builder), we need to unref it
    // But only if it's different from the main builder
    GtkBuilder *dialog_builder = GTK_BUILDER(g_object_get_data(G_OBJECT(dialog), "dialog_builder"));
    if (dialog_builder && dialog_builder != main_builder) {
        g_object_unref(dialog_builder);
    }
}

void SerialManager::update_serial_config_from_ui(GtkBuilder *builder) {
    // Note: This function is called from the dialog response callback with the main builder
    // But we need to get the dialog widgets from the dialog builder which was saved in the dialog's user data
    // However, since we don't have direct access to the dialog widget here, we'll use the builder passed to this function
    // which should be the dialog builder when called correctly from the response handler
    
    // Assume the builder passed to this function is the dialog builder
    // This is the case when the function is called correctly from the dialog response handler
    GtkBuilder *dialog_builder = builder;
    
    GtkWidget *port_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "port_combobox"));
    GtkWidget *baudrate_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "baudrate_combobox"));
    GtkWidget *stopbits_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "stopbits_combobox"));
    GtkWidget *databits_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "databits_combobox"));
    GtkWidget *parity_combobox = GTK_WIDGET(gtk_builder_get_object(dialog_builder, "parity_combobox"));
    
    std::cout << "开始更新串口配置..." << std::endl;
    
    if (port_combobox) {
        const gchar *port_text = gtk_combo_box_get_active_id(GTK_COMBO_BOX(port_combobox));
        std::string old_port = baseConfig.port;
        baseConfig.port = port_text ? port_text : "/dev/ttyUSB0";
        std::cout << "端口从 " << old_port << " 更新为 " << baseConfig.port << std::endl;
    }
    
    if (baudrate_combobox) {
        const gchar *baudrate_text = gtk_combo_box_get_active_id(GTK_COMBO_BOX(baudrate_combobox));
        int old_baudrate = baseConfig.baudRate;
        if (baudrate_text) {
            try {
                baseConfig.baudRate = std::stoi(baudrate_text);
            } catch (...) {
                baseConfig.baudRate = 9600;
            }
        } else {
            baseConfig.baudRate = 9600;
        }
        std::cout << "波特率从 " << old_baudrate << " 更新为 " << baseConfig.baudRate << std::endl;
    }
    
    if (stopbits_combobox) {
        const gchar *stopbits_text = gtk_combo_box_get_active_id(GTK_COMBO_BOX(stopbits_combobox));
        int old_stopbits = baseConfig.stopBits;
        if (stopbits_text) {
            try {
                baseConfig.stopBits = std::stoi(stopbits_text);
            } catch (...) {
                baseConfig.stopBits = 1;
            }
        } else {
            baseConfig.stopBits = 1;
        }
        std::cout << "停止位从 " << old_stopbits << " 更新为 " << baseConfig.stopBits << std::endl;
    }
    
    if (databits_combobox) {
        const gchar *databits_text = gtk_combo_box_get_active_id(GTK_COMBO_BOX(databits_combobox));
        int old_databits = baseConfig.dataBits;
        if (databits_text) {
            try {
                baseConfig.dataBits = std::stoi(databits_text);
            } catch (...) {
                baseConfig.dataBits = 8;
            }
        } else {
            baseConfig.dataBits = 8;
        }
        std::cout << "数据位从 " << old_databits << " 更新为 " << baseConfig.dataBits << std::endl;
    }
    
    if (parity_combobox) {
        const gchar *parity_text = gtk_combo_box_get_active_id(GTK_COMBO_BOX(parity_combobox));
        std::string old_parity = baseConfig.parity;
        baseConfig.parity = parity_text ? parity_text : "none";
        std::cout << "校验位从 " << old_parity << " 更新为 " << baseConfig.parity << std::endl;
    }
    
    std::cout << "串口配置更新完成" << std::endl;
}